<template>
  <div>
    <el-form label-position="top" :disabled="readonly">
      <!-- <div v-for="(item, index) in podScheduleItems" :key="index">
        <el-card style="margin-top: 10px">
          <div class="w-full justify-end flex">
            <el-button
              link
              type="danger"
              @click="handlePodScheduleDelete(index)"
            >
              {{ $t("commons.button.delete") }}
            </el-button>
          </div>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item :label="$t('business.workload.type')">
                <ko-data-item
                  v-model="item.type"
                  itemType="radio"
                  :radios="options.type_list"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item :label="$t('business.workload.priority')">
                <ko-data-item
                  v-model="item.priority"
                  itemType="radio"
                  :radios="options.priority_list"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col v-if="item.priority === 'Preferred'" :span="12">
              <el-form-item :label="$t('business.workload.weight')">
                <ko-data-item v-model="item.weight" itemType="number" />
              </el-form-item>
            </el-col>
          </el-row>

          <div style="margin-top: 20px">
            <span>matchExpressions</span>
          </div>
          <ko-match-table
            v-model:match-rules="item.rules"
            :readonly="readonly"
          />

          <div style="margin-top: 20px"><span>matchLabels</span></div>
          <table style="width: 100%; margin-top: 5px" class="tab-table">
            <tr
              v-for="(row, index) in item.labelRules"
              v-bind:key="'l' + index"
            >
              <td width="48%">
                <ko-data-item v-model="row.key" itemType="input" />
              </td>
              <td width="48%">
                <ko-data-item v-model="row.value" itemType="input" />
              </td>
              <td>
                <el-button
                  type="text"
                  style="font-size: 10px"
                  @click="handlePodScheduleItemDeleteLabelRule(item, index)"
                >
                  {{ $t("commons.button.delete") }}
                </el-button>
              </td>
            </tr>
            <tr>
              <td align="left">
                <el-button @click="handlePodScheduleItemAddLabelRule(item)">
                  {{ $t("commons.button.add") }}
                </el-button>
              </td>
            </tr>
          </table>

          <el-row style="margin-top: 10px">
            <el-col :span="24">
              <el-form-item
                :label="$t('business.workload.topology_key')"
                required
              >
                <ko-data-item
                  v-model="item.topologyKey"
                  itemType="input"
                  placeholder="e.g. failure-domain.beta.kubernetes.io/zone"
                />
              </el-form-item>
            </el-col>
          </el-row>
        </el-card>
      </div>
      <el-button @click="handlePodScheduleAdd()">
        {{ $t("commons.button.add") }} Pod
        {{ $t("business.workload.rules") }}
      </el-button>

      <div v-for="(item, index) in nodeScheduleItems" :key="'n' + index">
        <el-card style="margin-top: 10px">
          <div class="w-full justify-end flex">
            <el-button
              type="danger"
              link
              @click="handleNodeScheduleDelete(index)"
            >
              {{ $t("commons.button.delete") }}
            </el-button>
          </div>
          <el-row>
            <el-col :span="12">
              <el-form-item :label="$t('business.workload.priority')">
                <ko-data-item
                  v-model="item.priority"
                  itemType="radio"
                  :radios="options.priority_list"
                />
              </el-form-item>
            </el-col>
            <el-col v-if="item.priority === 'Preferred'" :span="12">
              <el-form-item :label="$t('business.workload.weight')">
                <ko-data-item v-model="item.weight" itemType="number" />
              </el-form-item>
            </el-col>
          </el-row>

          <div style="margin-top: 20px"><span>matchLabels</span></div>
          <ko-match-table
            v-model:match-rules="item.rules"
            :readonly="readonly"
          />
          <div style="margin-top: 20px"><span>matchFields</span></div>
          <ko-match-table
            v-model:match-rules="item.fields"
            :readonly="readonly"
          />
        </el-card>
      </div>
      <el-button @click="handleNodeScheduleAdd()">
        {{ $t("commons.button.add") }} Node
        {{ $t("business.workload.rules") }}
      </el-button> -->
      <k-section type="simple">
        <template #head>
          <k-segment
            v-model="scheduleType"
            :options="options.scheduleTypeOptions"
            @change="onScheduleTypeChanged"
          />
        </template>
        <el-collapse-transition>
          <div v-if="scheduleType === 'Default'">
            <el-text>
              {{ "按照默认规则将副本调度到节点上" }}
            </el-text>
          </div>
          <div v-else-if="scheduleType === 'Centralized'">
            <el-text>
              {{ "将副本尽可能调度到同一节点上" }}
            </el-text>
          </div>
          <div v-else-if="scheduleType === 'Distributed'">
            <el-text>
              {{ "将副本尽可能调度到不同节点上" }}
            </el-text>
          </div>
          <k-section
            v-else-if="scheduleType === 'Custom'"
            type="simple"
            class="w-full flex flex-col"
          >
            <div
              v-for="(rule, idx) in customScheduleRules"
              :key="idx"
              class="flex gap-2 items-center mb-2"
            >
              <ko-data-item
                v-model="rule.type"
                item-type="select"
                :options="options.type_list"
                placeholder="类型"
                @on-change="syncToModel"
              />
              <ko-data-item
                v-model="rule.priority"
                item-type="select"
                :options="options.priority_list"
                placeholder="策略"
                @on-change="syncToModel"
              />

              <ko-data-item
                v-model="rule.key"
                item-type="input"
                placeholder="label匹配的建"
                :default="InjectLabelKey.AppName"
                @on-change="syncToModel"
              />

              <ko-data-item
                v-model="rule.operator"
                item-type="select"
                :options="options.operator_list"
                placeholder="匹配方式"
                @on-change="syncToModel"
              />

              <ko-data-item
                v-model="rule.value"
                item-type="input"
                placeholder="label匹配的值"
                @on-change="syncToModel"
              />
            </div>

            <div class="w-full justify-end flex">
              <el-button
                icon="Plus"
                circle
                @click="customScheduleRules.push({})"
              />
            </div>
          </k-section>
        </el-collapse-transition>
      </k-section>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import {
  InjectLabelKey,
  LabelSelectorOperator,
  Namespace,
  ObjectMeta,
  PodAffinityTerm,
  PodSpec
} from "@/views/domain/kubeHud/api/k8s";
import { objectToList } from "@/views/domain/kubeHud/utils";
import KoDataItem from "@/views/domain/kubeHud/views/components/ko-data-item/index.vue";
import KoMatchTable from "@/views/domain/kubeHud/views/components/ko-workloads/ko-match-table.vue";
import KSegment from "@/views/domain/kubeHud/views/components/k-segment/index.vue";
import KSection from "@/views/domain/kubeHud/views/components/k-section/index.vue";

import { computed, onMounted, reactive, ref } from "vue";
import { useI18n } from "vue-i18n";

const { t } = useI18n();

type Prop = {
  readonly?: boolean;
};

const props = withDefaults(defineProps<Prop>(), {});
const metadata = defineModel<ObjectMeta>("metadata");
const spec = defineModel<PodSpec>("spec");
const affinity = computed(() => spec.value.affinity);

const scheduleType = ref<"Default" | "Centralized" | "Distributed" | "Custom">(
  "Default"
);
const options = reactive({
  scheduleTypeOptions: [
    { label: t("business.workload.schedule_engine.default"), value: "Default" },
    {
      label: t("business.workload.schedule_engine.centralized"),
      value: "Centralized"
    },
    {
      label: t("business.workload.schedule_engine.distributed"),
      value: "Distributed"
    },
    { label: t("business.workload.schedule_engine.custom"), value: "Custom" }
  ],

  type_list: [
    {
      label: t("business.workload.schedule_engine.affinity"),
      value: "Affinity"
    },
    {
      label: t("business.workload.schedule_engine.anti_affinity"),
      value: "Anti-Affinity"
    }
  ],
  priority_list: [
    { label: t("business.workload.preferred"), value: "Preferred" },
    { label: t("business.workload.required"), value: "Required" }
  ],
  namespace_operation_list: [
    {
      label: t("business.workload.this_namespace"),
      value: "podNamespace"
    },
    {
      label: t("business.workload.these_namespace"),
      value: "selectNamespace"
    }
  ],
  operator_list: [
    { label: "<", value: "Lt" },
    { label: ">", value: "Gt" },
    { label: "Exists", value: "Exists" },
    { label: "Not Exist", value: "DoesNotExist" },
    { label: "In", value: "In" },
    { label: "Not In", value: "NotIn" }
  ]
});

type CustomScheduleItem = {
  type?: "Affinity" | "Anti-Affinity";
  priority?: "Preferred" | "Required";
  key?: string;
  value?: string;
  operator?: LabelSelectorOperator;
};

const customScheduleRules = ref<CustomScheduleItem[]>([]);
const syncToModel = async () => {
  affinity.value.podAffinity = {
    requiredDuringSchedulingIgnoredDuringExecution: [],
    preferredDuringSchedulingIgnoredDuringExecution: []
  };
  affinity.value.podAntiAffinity = {
    requiredDuringSchedulingIgnoredDuringExecution: [],
    preferredDuringSchedulingIgnoredDuringExecution: []
  };
  delete affinity.value.nodeAffinity;

  for (const rule of customScheduleRules.value) {
    let term: PodAffinityTerm = {
      topologyKey: InjectLabelKey.Hostname,
      labelSelector: {
        matchExpressions: [
          {
            key: rule.key,
            operator: rule.operator,
            values: [rule.value]
          }
        ]
      }
    };

    switch (`${rule.type}_${rule.priority}`) {
      case "Affinity_Preferred":
        affinity.value.podAffinity.preferredDuringSchedulingIgnoredDuringExecution.push(
          {
            weight: 100,
            podAffinityTerm: term
          }
        );
        break;
      case "Affinity_Required":
        affinity.value.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.push(
          term
        );
        break;
      case "Anti-Affinity_Preferred":
        affinity.value.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.push(
          {
            weight: 100,
            podAffinityTerm: term
          }
        );
        break;
      case "Anti-Affinity_Required":
        affinity.value.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution.push(
          term
        );
        break;
    }
  }
};

const onScheduleTypeChanged = (type: string) => {
  switch (type) {
    case "Default":
      spec.value.affinity = {};
      break;
    case "Centralized":
      spec.value.affinity = {
        podAffinity: {
          preferredDuringSchedulingIgnoredDuringExecution: [
            {
              weight: 100,
              podAffinityTerm: {
                topologyKey: InjectLabelKey.Hostname,
                labelSelector: {
                  matchLabels: metadata.value?.labels ?? {}
                }
              }
            }
          ]
        }
      };
      break;
    case "Distributed":
      spec.value.affinity = {
        podAntiAffinity: {
          preferredDuringSchedulingIgnoredDuringExecution: [
            {
              weight: 100,
              podAffinityTerm: {
                topologyKey: InjectLabelKey.Hostname,
                labelSelector: {
                  matchLabels: metadata.value?.labels ?? {}
                }
              }
            }
          ]
        }
      };
      break;
    case "Custom":
      customScheduleRules.value = [{}];
      break;
  }
};
/**
const options = reactive({
  type_list: [
    { label: t("business.workload.affinity"), value: "Affinity" },
    {
      label: t("business.workload.anti_affinity"),
      value: "Anti-Affinity"
    }
  ],
  priority_list: [
    { label: t("business.workload.preferred"), value: "Preferred" },
    { label: t("business.workload.required"), value: "Required" }
  ],
  namespace_operation_list: [
    {
      label: t("business.workload.this_namespace"),
      value: "podNamespace"
    },
    {
      label: t("business.workload.these_namespace"),
      value: "selectNamespace"
    }
  ],
  operator_list: [
    { label: "<", value: "Lt" },
    { label: ">", value: "Gt" },
    { label: "Exists", value: "Exists" },
    { label: "Not Exist", value: "DoesNotExist" },
    { label: "=", value: "In" },
    { label: "!=", value: "NotIn" }
  ]
});

type ScheduleType = "Affinity" | "Anti-Affinity";
type SchedulePriority = "Preferred" | "Required";
type ScheduleExpression = {
  key?: string;
  operator?: string;
  value?: string;
};
type SchedulingItem = {
  type?: ScheduleType;
  priority: SchedulePriority;
  weight?: number;
  rules?: ScheduleExpression[];
  fields?: ScheduleExpression[];
  labelRules?: any[];
  topologyKey?: string;
};

const podScheduleItems = ref<SchedulingItem[]>([]);
const nodeScheduleItems = ref<SchedulingItem[]>([]);

const handlePodScheduleAdd = () => {
  podScheduleItems.value.push({
    type: "Affinity",
    priority: "Preferred",
    weight: 1,
    rules: [],
    labelRules: [],
    topologyKey: ""
  });
};

const handlePodScheduleDelete = (index: number) => {
  podScheduleItems.value.splice(index, 1);
};

const handlePodScheduleItemAddLabelRule = (item: SchedulingItem) => {
  item.labelRules.push({
    key: "",
    value: ""
  });
};

const handlePodScheduleItemDeleteLabelRule = (
  item: SchedulingItem,
  index: number
) => {
  item.labelRules.splice(index, 1);
};

const handleNodeScheduleAdd = () => {
  nodeScheduleItems.value.push({
    priority: "Preferred",
    weight: 1,
    rules: [],
    labelRules: [],
    fields: [],
    topologyKey: ""
  });
};

const handleNodeScheduleDelete = (index: number) => {
  nodeScheduleItems.value.splice(index, 1);
};

// 原始数据转ui数据
const convertMatchExpress = (rules: any[]) => {
  return rules.map(rule => ({
    key: rule.key,
    operator: rule.operator,
    ...(rule.value ? { values: rule.value.split(",") } : {})
  }));
};

const parsePodScheduleItem = (
  type: ScheduleType,
  priority: SchedulePriority,
  src: PodAffinityTerm
): SchedulingItem => {
  return {
    type,
    priority,
    topologyKey: src.topologyKey,
    labelRules: objectToList(src.labelSelector?.matchLabels),
    rules: src.labelSelector?.matchExpressions?.map(exp => ({
      key: exp.key,
      operator: exp.operator,
      value: exp.values?.join(",")
    }))
  };
};

const reloadPodScheduleObject = (spec: PodSpec) => {
  podScheduleItems.value = [];
  nodeScheduleItems.value = [];
  if (spec.affinity?.podAffinity) {
    podScheduleItems.value.push(
      ...(spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution?.map(
        term => {
          return parsePodScheduleItem("Affinity", "Required", term);
        }
      ) ?? [])
    );

    podScheduleItems.value.push(
      ...(spec.affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution?.map(
        term => {
          return parsePodScheduleItem(
            "Affinity",
            "Preferred",
            term.podAffinityTerm
          );
        }
      ) ?? [])
    );
  }

  if (spec.affinity?.podAntiAffinity) {
    podScheduleItems.value.push(
      ...(spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution?.map(
        term => {
          return parsePodScheduleItem("Anti-Affinity", "Required", term);
        }
      ) ?? [])
    );

    podScheduleItems.value.push(
      ...(spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution?.map(
        term => {
          return parsePodScheduleItem(
            "Anti-Affinity",
            "Preferred",
            term.podAffinityTerm
          );
        }
      ) ?? [])
    );
  }

  if (spec.affinity?.nodeAffinity) {
    nodeScheduleItems.value.push(
      ...(spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution?.nodeSelectorTerms?.map(
        (term): SchedulingItem => {
          return {
            priority: "Required",
            fields: term.matchFields?.map(f => ({
              key: f.key,
              operator: f.operator,
              value: f.values?.join(",")
            })),
            rules: term.matchExpressions?.map(exp => ({
              key: exp.key,
              operator: exp.operator,
              value: exp.values?.join(",")
            }))
          };
        }
      ) ?? [])
    );
    nodeScheduleItems.value.push(
      ...spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution?.map(
        (term): SchedulingItem => {
          return {
            priority: "Preferred",
            rules: term.preference?.matchExpressions?.map(exp => ({
              key: exp.key,
              operator: exp.operator,
              value: exp.values?.join(",")
            })),
            fields: term.preference?.matchFields?.map(f => ({
              key: f.key,
              operator: f.operator,
              value: f.values?.join(",")
            }))
          };
        }
      )
    );
  }
};

onMounted(() => {
  reloadPodScheduleObject(spec.value);
});
*/
</script>
